package com.org.redis.limit;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.concurrent.TimeUnit;

@Aspect
@Component
public class SaverHandler {

    @Resource
    private RedisTemplate<String,Integer> redisTemplate;
    @Resource
    private HttpServletRequest request;
    private final long expire = 60;
    private final Integer n = 100;

    @Pointcut("@annotation(com.org.redis.limit.Saver)")
    public void saver(){}

    @Around(value = "saver()")
    public Object doAround(ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature(); //获取调用的方法
        Method method = point.getTarget().getClass().getMethod(signature.getName(), signature.getMethod().getParameterTypes());
        Saver saver = method.getAnnotation(Saver.class);
        String key = saver.key();
        boolean open = saver.open();
        if(!open) return point.proceed(); //未开启ip监控

        if("ip".equals(key)){
            String ip = request.getRemoteAddr();
            System.out.println(ip);
            synchronized (ip){
                Integer value = redisTemplate.opsForValue().get(ip);
                if(value == null){
                    redisTemplate.opsForValue().set(ip, 1, expire, TimeUnit.SECONDS);
                }else if(value >= n){
                    redisTemplate.opsForValue().set(ip, -1, expire, TimeUnit.SECONDS);
                    String msg = "你请求服务器过于频繁，请60秒后再试.";
                    return msg;
                }else if(value == -1){
                    String msg = "你请求服务器过于频繁，请60秒后再试.";
                    return msg;
                }else {
                    Long expire1 = redisTemplate.boundValueOps(ip).getExpire();//获取剩余的过期时间
                    redisTemplate.opsForValue().set(ip,value+1,expire1,TimeUnit.SECONDS);
                }
            }
        }
        return point.proceed();
    }
}
